<template>
  <Form ref="dom" :model="value">
    <Row :gutter="8">
      <template v-for="config in newConfigs"
        :key="config.key">
        <Col v-bind="config.wrapperCol"
          v-if="config.when(value)">
        <FormItem v-bind="config.formItemAttrs"
          :label-col="config.labelCol">
          <Switch
            v-if="config.type.name === 'ASwitch'"
            v-bind="config.componentAttrs"
            :checked="Boolean(value[config.key])"
            @update:checked="(e) => {
                handleChange({
                  key: config.key,
                  value: config.componentAttrs?.useNumber ? +e : e,
                });
                config.componentAttrs.onChange?.({ update: handleChange, value: value });
              }
              " />
          <component v-else :is="config.type"
            v-bind="config.componentAttrs"
            :config="config"
            :value="value[config.key]"
            :raw="config.raw" @update:value="(e: string | number | any) => {
              if (e?.key) {
                handleChange({ key: e.key, value: e.value });
              } else {
                handleChange({ key: config.key, value: e });
              }
              config.componentAttrs.onChange?.({ update: handleChange, value: value })
            }" />
        </FormItem>
        </Col>
      </template>
      <slot />
    </Row>
  </Form>
</template>
<script lang="tsx" setup>
import {
  Col, Form, Row, Switch,
} from 'ant-design-vue';
import {
  computed, onMounted, PropType, ref,
} from 'vue';

import { FormItemConfig } from './ConfigFormType';

const FormItem = Form.Item;

const props = defineProps({
  configs: {
    type: Array as PropType<FormItemConfig[]>,
    default: () => [],
  },
  form: {
    type: Object,
    default: () => ({}),
  },
  value: {
    type: Object,
    default: () => ({}),
  },
  labelCol: {
    type: Object,
    default: () => ({}),
  },
  readonly: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  wrapperCol: {
    type: Object,
    default: () => ({}),
  },
});
const emit = defineEmits(['change', 'update:value', 'update:form']);
const newConfigs = computed(() => props.configs.map((config) => {
  const {
    wrapperCol, labelCol, when, type, key = '', attrs, children, model, ...rest
  } = config;
  const formItemAttrs = {
    name: key,
    model,
    ...rest,
  } as Record<string, any>;
  const componentAttrs = {
    ...attrs,
    disabled: Boolean(props.disabled || attrs?.disabled),
    readonly: Boolean(props.readonly || attrs?.readonly),
  } as Record<string, any>;

  return {
    key,
    name: [key],
    type,
    children,
    when: when || (() => true),
    labelCol: labelCol || props.labelCol || {},
    wrapperCol: wrapperCol || props.wrapperCol || {},
    componentAttrs,
    formItemAttrs,
    raw: config,
  };
}));

const handleChange = ({ key, value }: any) => {
  const temp = props.value;
  temp[key] = value;
  emit('update:value', temp);
  emit('change', { key, value });
};
const dom = ref();
onMounted(() => {
  emit('update:form', dom.value);
});
</script>

<style></style>
